#include "LecteurPhraseSimple.h"

#include <stdlib.h>
#include <iostream>
using namespace std;

////////////////////////////////////////////////////////////////////////////////
LecteurPhraseSimple::LecteurPhraseSimple(string nomFich) :
	ls(nomFich) {
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::analyse() {
	programme();
	cout << "Syntaxe correcte." << endl;
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::programme() {
// <programme> ::= debut <seqInst> fin FIN_FICHIER

	sauterSymCour("debut");
	seqInst();
	sauterSymCour("fin");
	testerSymCour("<FINDEFICHIER>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::seqInst() {
// <seqInst> ::= <inst> ; { <inst> ; }

	do {
		inst();
		sauterSymCour(";");
	} while (ls.getSymCour()=="<VARIABLE>" ||
                ls.getSymCour() == "si"||
                ls.getSymCour() == "tantque"||
                ls.getSymCour() == "repeter" ||
                ls.getSymCour() == "lire"||
                ls.getSymCour() == "ecrire"||
                ls.getSymCour() == "pour"||
                ls.getSymCour() == "switch");
	// tant que le symbole courant est un debut possible d'instruction...
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::inst() {
//  <inst> ::= <affectation> | <instSi> | <instTq> | <instRepeter>
    if(ls.getSymCour() == "<VARIABLE>")
	affectation();
    else if (ls.getSymCour() == "si")
        instSi();
    else if (ls.getSymCour() == "tantque")
        instTq();
    else if (ls.getSymCour() == "repeter")
        instRepeter();
    else if (ls.getSymCour() == "lire")
        instLire();
    else if (ls.getSymCour() == "ecrire")
        instEcrire();
    else if (ls.getSymCour() == "pour")
        instPour();
    else if (ls.getSymCour() == "switch")
        instSwitchCase();
    else
        erreur("<inst>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::affectation() {
// <affectation> ::= <variable> = <expression>
	sauterSymCour("<VARIABLE>");
	sauterSymCour("=");
	expression();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::expression() {
// <expression> ::= <facteur> { <opAdd> <facteur> }
	terme();
	while (ls.getSymCour()=="+" || ls.getSymCour()=="-") {
		opAdd();
		terme();
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::facteur() {
// <facteur> ::= <entier>  |  <variable>  |  - <facteur>  |  ( <expression> ) | <chaine>

	if (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="<ENTIER>")
		ls.suivant();
	else if (ls.getSymCour()=="-" || ls.getSymCour()=="non") {
            opUnaire();
            expBoolOu();
	} else if (ls.getSymCour()=="(") {
		ls.suivant();
		expBoolOu();
		sauterSymCour(")");
	}else if (ls.getSymCour()=="<CHAINE>")
            ls.suivant();
        else
		erreur("<facteur>");
}

//////////////////////////////////////////////////////////////////////////////////
//void LecteurPhraseSimple::opBinaire()
//// <opBinaire> ::= + | - | *  | /
//{
//	if (ls.getSymCour()=="+" || ls.getSymCour()=="-" ||
//		ls.getSymCour()=="*" || ls.getSymCour()=="/")
//		ls.suivant();
//	else
//		erreur("<opBinaire>");
//}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::testerSymCour(string ch) {
	if (ls.getSymCour() != ch) {
		cout << endl << "-------- Erreur ligne " << ls.getLigne()
				<< " - Colonne " << ls.getColonne() << endl << "   Attendu : "
				<< ch << endl << "   Trouve  : " << ls.getSymCour() << endl
				<< endl;
		exit(0); // plus tard, on levera une exception
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::sauterSymCour(string ch) {
	testerSymCour(ch);
	ls.suivant();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::erreur(string mess) {
	cout << endl << "-------- Erreur ligne " << ls.getLigne() << " - Colonne "
			<< ls.getColonne() << endl << "   Attendu : " << mess << endl
			<< "   Trouve  : " << ls.getSymCour() << endl << endl;
	exit(0); // plus tard, on levera une exception
}

void LecteurPhraseSimple::terme(){
   // <terme>::=<facteur>{<oppMult><facteur>}
    facteur();
    while(ls.getSymCour() == "*" || ls.getSymCour() =="/"){
        oppMult();
        facteur();
    }
}

void LecteurPhraseSimple::opAdd(){
    //<opAdd>:: = + | -
    if(ls.getSymCour() == "+" || ls.getSymCour() == "-")
        ls.suivant();
    else
        erreur("<oppAdd>");
}

void LecteurPhraseSimple::oppMult(){
    //<opMult>::=* | /
    if(ls.getSymCour() == "*" || ls.getSymCour() == "/")
        ls.suivant();
    else
        erreur("<oppMult>");
}

void LecteurPhraseSimple::expBoolOu(){
    //<expBoolOu>::=<expBoolEt> {ou <expBoolEt>}
    expBoolEt();
    while(ls.getSymCour()=="ou") {
        ls.suivant();
        expBoolEt();
    }
}

void LecteurPhraseSimple::expBoolEt(){
    //<expBoolEt>::=<relation> {et <relation>}
    relation();
    while(ls.getSymCour()=="et"){
        ls.suivant();
        relation();
    }
}

void LecteurPhraseSimple::relation(){
    //<relation>::=<expresion>{<opRel><expression>}
    expression();
    while(ls.getSymCour()=="==" || ls.getSymCour()=="!=" ||ls.getSymCour()=="<" ||ls.getSymCour()=="<=" ||ls.getSymCour()==">" || ls.getSymCour()==">="){
        opRel();
        expression();
    }
}
void LecteurPhraseSimple::opRel(){
    //<opRel>::= == | != | <= | < | > | >=
    if(ls.getSymCour()=="==" || ls.getSymCour()=="!=" ||ls.getSymCour()=="<" ||ls.getSymCour()=="<=" ||ls.getSymCour()==">" || ls.getSymCour()==">=")
        ls.suivant();
    else
        erreur("<opRel>");
}

void LecteurPhraseSimple::opUnaire(){
    //<opUnaire>::= - | non
    if(ls.getSymCour()=="-" || ls.getSymCour()=="non")
            ls.suivant();
    else
        erreur("<opUnitaire>");
}

void LecteurPhraseSimple::instSi(){
    //<instSi> ::= si ( <expBoolOu> ) <seqInst> { sinonsi ( <expBoolOu> ) <seqInst> }[ sinon <seqInst> ] finsi
    sauterSymCour("si");
    sauterSymCour("(");
    expBoolOu();
    sauterSymCour(")");
    seqInst();
    while(ls.getSymCour()=="sinonsi"){
        ls.suivant();
        sauterSymCour("(");
        expBoolOu();
        sauterSymCour(")");
        seqInst();
    }
    if(ls.getSymCour()=="sinon"){
        ls.suivant();
        seqInst();
    }
    sauterSymCour("finsi");
}

void LecteurPhraseSimple::instTq(){
    //<instTq> ::= tantque ( <expBoolOu> ) <seqInst> fintantque
    sauterSymCour("tantque");
    sauterSymCour("(");
    expBoolOu();
    sauterSymCour(")");
    seqInst();
    sauterSymCour("fintantque");
}

void LecteurPhraseSimple::instRepeter(){
    //<instRepeter> ::= repeter <seqInst> jusqua ( <expBoolOu> )
    sauterSymCour("repeter");
    seqInst();
    sauterSymCour("jusqua");
    sauterSymCour("(");
    expBoolOu();
    sauterSymCour(")");
}

void LecteurPhraseSimple::instLire(){
    sauterSymCour("lire");
    sauterSymCour("(");
    if(ls.getSymCour()=="<VARIABLE>")
        ls.suivant();
    else
        erreur("<lire>");
    sauterSymCour(")");
}

void LecteurPhraseSimple::instEcrire(){
    sauterSymCour("ecrire");
    sauterSymCour("(");
    if(ls.getSymCour()=="<CHAINE>")
        ls.suivant();
    else
        expression();
    sauterSymCour(")");
}

void LecteurPhraseSimple::instPour(){
//<instPour>::=pour([<affectation>{,<affectation>}];<expBoolOu>;[<affectation>{,<affectation>}])<seqInst> finpour
    sauterSymCour("pour");
    sauterSymCour("(");
    if(ls.getSymCour()=="<VARIABLE>"){
        affectation();
        while(ls.getSymCour()==","){
            ls.suivant();
            affectation();
        }
    }
    sauterSymCour(";");
    if(ls.getSymCour()== "<VARIABLE>" ||
            ls.getSymCour()== "<ENTIER>" ||
            ls.getSymCour()== "-" ||
            ls.getSymCour()== "(")
        expBoolOu();
    else
        erreur("<expBoolOu>");
    sauterSymCour(";");
    if(ls.getSymCour()=="<VARIABLE>"){
        affectation();
        while(ls.getSymCour()==","){
            ls.suivant();
            affectation();
        }
    }
    sauterSymCour(")");
    seqInst();
    sauterSymCour("finpour");
}

void LecteurPhraseSimple::instSwitchCase(){
    //<instSwitchCase> ::= switch ( <variable> ) { case <entier> : <seqInst> } default : <seqInst>
    sauterSymCour("switch");
    sauterSymCour("(");
    if(ls.getSymCour()== "<VARIABLE>")
        ls.suivant();
     else
         erreur("<VARIABLE>");

    sauterSymCour(")");
    while(ls.getSymCour()=="case"){
        ls.suivant();
    if(ls.getSymCour()== "<ENTIER>")
        ls.suivant();
     else
        erreur("<ENTIER>");

        sauterSymCour(":");
        seqInst();
     }
        sauterSymCour("default");
        sauterSymCour(":");
        seqInst();
        sauterSymCour("finswitch");
}